<?php

namespace App\Services\Draw\DrawObject;


use App\Exceptions\BasicException;
use App\Jobs\QiPao\Draw\DrawStatisticsJob;
use App\Models\MainDB\AccountLog;
use App\Models\MainDB\GiftBackpack;
use App\Models\MainDB\User as MainUserModel;
use App\Repositories\GiftRepository;
use App\Repositories\UserDataRepository;
use App\Services\Draw\DrawConst\CacheKey;
use App\Services\Draw\Enum\DrawEnum;
use App\Services\Draw\Traits\Redis;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\DB;
use App\Services\Tools\RedisService;

/**
 * 抽奖实体
 * @author
 */
abstract class Draw
{

    protected $poolConfigModel;
    protected $poolUserModel;
    protected $poolModel;
    protected $poolPrizeModel;
    protected $poolGroupModel;
    protected $poolQueueModel;
    protected $poolTemplateModel;
    protected $poolDrawModel;
    protected $poolDrawRecordModel;
    protected $giftTemplateModel;
    protected $levelModel;
    protected $criticalGiftModel;
    protected $criticalDrawRecordModel;
    protected $poolIndependentModel;
    protected $poolIndependentPrizeModel;
    protected $appointGiftModel;
    protected $fragmentGroupModel;
    protected $fragmentUserRecordModel;
    protected $fragmentPoolRecordModel;
    protected $fragmentPoolModel;

    protected $checkRecordModel;
    protected $addPoolAccountRecordModel;
    protected $addPoolRepo;

    protected $cachePrefix = '';
    protected $privateKey = '';//用于辨别游戏gashapon、pet、stellar
    protected $drawLockKey = "draw:lock_";
    protected $queuePoolGroup;
    protected $independentPoolGroup;
    protected $publicPoolGroup;
    protected $novicePoolGroup;

    protected $isDrawCriticalGift = false;
    protected $isDrawAccumulate = true; //是否做抽奖计数累计逻辑
    protected $isNovicePreset = false; //是否新手奖池预设
    protected $redisObject; //是否做抽奖计数累计逻辑
    protected $game_name = 'draw';

    protected $wholePrefix = 'whole_game:';
    private  $user_info;//用户的游戏信息，仅用于自动购买的判断



//    protected $userDatePutRecordCacheKey = "draw:user:put:date";
//    protected $userWeekPutRecordCacheKey = "draw:user:put:week";
//    protected $poolDatePutRecordCacheKey = "draw:pool:put:date";
//    protected $poolWeekPutRecordCacheKey = "draw:pool:put:week";
//    protected $poolRoundCacheKey = "draw:pool:round";
//    protected $dateRankCacheKey = "draw:rank:date";
//    protected $weekRankCacheKey = "draw:rank:week";
//    protected $monthRankCacheKey = "draw:rank:month";

//    protected $poolGroupRemainCountCacheKey = "poolGroup:remainCount";

    public function __construct()
    {
        $this->addPoolRepo = app('repo_add_pool');

    }

    /**
     * 校验游戏是否开启
     * @return mixed
     */
    public function checkIsOpen()
    {
        $poolConfig = $this->poolConfigModel->one(['id' => 1], ['switch']);
        if ($poolConfig->switch) {
            //公共池
            $where = ['a.tag' => 'public', 'b.status' => 1];
            $template_public_count = $this->poolModel->from($this->poolModel->getTable().' as a')
                ->join($this->poolGroupModel->getTable().' as b', 'a.id', '=', 'b.pool_id')
                ->where($where)->count();
            if ($template_public_count < 2) {
                $poolConfig->switch = 0;
            }
            //新手池
            $where['a.tag'] = 'novice';
            $template_novice_count = $this->poolModel->from($this->poolModel->getTable().' as a')
                ->join($this->poolGroupModel->getTable().' as b', 'a.id', '=', 'b.pool_id')
                ->where($where)->count();
            if ($template_novice_count < 2) {
                $poolConfig->switch = 0;
            }
        }
        return $poolConfig->switch;
    }

    public function getCriticalGiftList()
    {
        $criticalGiftList = $this->criticalGiftModel->getListWithLevel(['status' => 1], ['name as mark_name', $this->criticalGiftModel->getTable() . '.level as critical_gift_level', 'gift_id']);

        $giftIds     = $criticalGiftList->pluck('gift_id')->toArray();
        $gifts       = (new GiftRepository())->giftsByIdsWithField($giftIds, ['id', 'title as name', 'price', 'img as picture']); // 抽中礼物信息
        $giftsWithId = $gifts->keyBy('id');
        foreach ($criticalGiftList as &$gift) {
            $gift['price']   = $giftsWithId[$gift['gift_id']]['price'];
            $gift['name']    = $giftsWithId[$gift['gift_id']]['name'];
            $gift['picture'] = $giftsWithId[$gift['gift_id']]['picture'];
        }
        $criticalGiftList = $criticalGiftList->sortByDesc('critical_gift_level')->values()->toArray();

        return $criticalGiftList;
    }

    public function getPoolConfig()
    {
        //获取配置
        return $this->poolConfigModel->one(['id' => 1]);
    }

    public function getUserDrawInfo($userId)
    {
        //获取用户信息
        $userInfo   = $this->poolUserModel->firstOrCreate($userId);

        $poolConfig                 = $this->poolConfigModel->one(['id' => 1]);
        $userInfo['help_info']      = $poolConfig->help_info;
        $userInfo['balance_coin'] = $poolConfig->balance_coin;
        $userInfo['draw_list']  = explode(',',app('model_config')->getValue('FRAG_DRAW_INFO') ?: '1,10,100');
        $userInfo['coin']       = app('model_user_account')->where('user_id', $userId)->value('diamond');
        $userInfo['fragment_nums']  = $this->redisObject->get($this->privateKey.':fragment_pool:nums') ?? '0';
        return $userInfo;
    }

    public function getLevelList()
    {
        return $this->levelModel->listAll([], ['level', 'name', 'min_exp', 'max_exp']);
    }

    public function getRankList($userId, $type, $limit)
    {
        $is_last = app('request')->is_last ?? 0; //1 昨日 上周 上月
        $rankKey = "";
        switch ($type) {
            case 'week':
                $week_date = $is_last ? date('W', strtotime('last week')) : date("W");
                $rankKey = $this->cachePrefix . CacheKey::WEEK_RANK . "_" . $week_date;
                break;
            case 'month':
                $month_date = $is_last ? date('m', strtotime('last month')) : date("m");
                $rankKey = $this->cachePrefix . CacheKey::MONTH_RANK . "_" . $month_date;
                break;
            default:
                $date = $is_last ? date('Y-m-d', strtotime('-1 day')) : date("Y-m-d");
                $rankKey = $this->cachePrefix . CacheKey::DATE_RANK . "_" . $date;
        }

        $rankList = $this->redisObject->zrevrange($rankKey, 0, $limit - 1, "WITHSCORES");
        //获取用户当前的rank
        $userRank  = $this->redisObject->zrevrank($rankKey, $userId);
        $userScore = $this->redisObject->zscore($rankKey, $userId);

        return ["rank_list" => $rankList, "user_rank" => ['rank' => $userRank, 'score' => $userScore]];
    }

    public function getAllPrizeList()
    {
        $pool = $this->poolModel->where('tag', 'public')->first();
        $current_group_id = $pool->current_group_id;
        if (empty($current_group_id)) {
            $current_group_id = $this->poolGroupModel->where([
                'status' => 1, 'pool_id' => $pool->id, 'type' => 1,
            ])->value('id');
        }
        $templateList = $this->poolTemplateModel->from($this->poolTemplateModel->getTable(). ' as pt')
            ->join($this->giftTemplateModel->getTable(). ' as gt', 'pt.gift_template_id', '=', 'gt.id')
            ->selectRaw('gt.gift_id, gt.type, pt.count, gt.rate')
            ->where('pt.group_id', $current_group_id)
            ->get();
        $sum = $templateList->sum('count');
        $templateListAry = array_column($templateList->toArray(), NULL, 'gift_id');

        $giftIds      = $templateList->where('type', DrawEnum::NORMAL_GIFT_TYPE)->pluck('gift_id');
        $giftList     = (new GiftRepository())->giftsByIds($giftIds); // 抽中礼物信息
        $giftList     = $giftList->transform(function ($item) use ($sum, $templateListAry){
            $item->type = DrawEnum::NORMAL_GIFT_TYPE;
            if ($templateListAry[$item->id]['rate']) {
                $item->rate = number_format($templateListAry[$item->id]['rate'], 2);
            } else {
                $item->rate = number_format(round($templateListAry[$item->id]['count']/$sum, 4) * 100, 2);
            }
            $item->rate = $item->rate < 0.01 ? '0.01' : $item->rate;
            return $item;
        });
        return $giftList->sortByDesc('price')->values()->toArray();
    }

    public function swapBalance($userId, $count, $is_auto = 0)
    {
        DB::connection('mysql_game')->beginTransaction();
        DB::beginTransaction();
        $poolConfig = $this->poolConfigModel->one(['id' => 1]);
        try {

            $coin = $count * $poolConfig->balance_coin;

            $mainUser = app('model_user_account')->where('user_id', $userId)->lockForUpdate()->firstOrFail();
            if ($mainUser->diamond < $coin) {
                throw new BasicException(-1, '余额不足');
            }
            $before_money = $mainUser->diamond;
            $mainUser->diamond -= $coin;
            $mainUser->save();
            $ext = [
                'before_money' => $before_money,
                'after_money' => $mainUser->diamond,
            ];
            app('model_account_log')->addLog($userId, $coin, ($is_auto ? '自动' : '')."兑换游戏道具x{$count}", 13, 0, 0, $ext);

            //$this->poolUserModel->updateOrCreateBalance($userId, $count);
            $user = $this->poolUserModel::query()->where('user_id', $userId)->lockForUpdate()->first();
            if (!$user) {
                $user = $this->poolUserModel::query()->create(['user_id' => $userId, 'balance' => $count]);
            } else {
                $user->balance += $count;
                $user->save();
            }

            DB::connection('mysql_game')->commit();
            DB::commit();
        } catch (\Exception $exception) {
            DB::rollBack();
            DB::connection('mysql_game')->rollBack();
            throw new BasicException(-1, $exception->getMessage());
        }
        return $user;
    }

    public function draw(int $userId, int $drawCount, $balanceId = 0)
    {
        $lockKey = $this->drawLockKey . $userId;
        if (!$this->redisObject->setnx($lockKey, 1)) {
            throw new BasicException(-1, '抽奖太频繁,请稍后再试');
        }

        $this->redisObject->expire($lockKey, 2);

        try {
            //抽奖前判断清除日数据、周数据
            $this->clearUserIO($userId);
            if (!$this->checkDrawCount($drawCount)) {
                throw new BasicException(-1, '抽奖次数异常');
            }
            //判断用户余额是否充足
            if (!$this->checkUserBalance($userId, $drawCount)) {
                //是否自动购买
                if ($this->user_info->is_auto) {
                    $this->swapBalance($userId, $drawCount - $this->user_info->balance, $this->user_info->is_auto);
                } else {
                    throw new BasicException(340001, $this->balanceNotEnoughMsg);
                }
            }

            $balance = $this->getUserBalance($userId, $balanceId);
            //获取用户信息
            $user = $this->poolUserModel->one(['user_id' => $userId]);

            $poolConfig = $this->poolConfigModel->info();

            //获取用户的抽奖组合池
            //round修改为通过redis计算 取消加锁
            $poolGroup = $this->getUserPoolGroup($user, $drawCount, $poolConfig);

            if (empty($poolGroup)) {
                throw new BasicException(-1, '未找到匹配奖池');
            }
            $poolGroup->cachePrefix = $this->cachePrefix;
            $poolGroup->privateKey = $this->privateKey;
            //获取奖池奖品
            $poolPrizeList = new Collection();

            if ($poolGroup->group_id != 0) {
                $poolPrizeList = $poolGroup->getPoolPrizeList($user);
            }
        } catch (\Exception $e) {
            $this->redisObject->del($lockKey);
            $code = (in_array($e->getCode(), [340001, -1])) ? $e->getCode() : -1;
            throw new BasicException($code, $e->getMessage());
        }

        $nextLockKey = $this->cachePrefix.'next_'.$poolGroup->tag.'_'.$poolGroup->group_id;
        /*if ($this->redisObject->exists($nextLockKey)) {
            throw new BasicException(-1, '正在补充弹药中,请稍后再试...');
        }*/

        $poolUpdateData    = [];
        $poolIncrRound     = 0;
        $poolGroupIncRound = [];
        // redis key值存在期间 抽正常池子
        if ($this->redisObject->exists($nextLockKey) || $poolGroup->checkDrawRoundPrizeCount($poolPrizeList, $drawCount, $user, $poolConfig)) { // 可以抽本期奖池
            $drawPrizes = $poolGroup->drawPrizes($poolPrizeList, $poolConfig, $poolGroup, $user, $drawCount); // 改为只有礼物充足才抽本轮奖池
        } else { // 抽取下期奖池
            $this->redisObject->set($nextLockKey, 'lock', 'ex', 20, 'nx');
            //$drawPoolPrizes = [];
            // 改为礼物不充足, 加锁  随机新的当前groupId 并且填充到奖池里u
            $poolGroup              = $poolGroup->getNewPoolGroup();
            if (empty($poolGroup)) {
                throw new BasicException(-1, '未找到匹配奖池组合');
            }
            $poolGroup->cachePrefix = $this->cachePrefix;

            $poolTemplateGiftList                    = $this->getPoolTemplateGiftList($poolGroup)->toBase();
            $poolIncrRound                           = 1;// 奖池轮数增加
            $poolGroupIncRound[$poolGroup->group_id] = 1;// 奖池组合轮数增加

            /*if (!$this->redisObject->set($nextLockKey, 'lock', 'ex', 20, 'nx')) {
                throw new BasicException(-1, '正在补充弹药中,请稍后再试...');
            }*/
            // 创建下一轮奖品
            $poolGroup->createNextRoundPrizes($poolTemplateGiftList, $user, $drawCount);
            $drawPrizes = $poolGroup->drawPrizes($poolTemplateGiftList, $poolConfig, $poolGroup, $user, $drawCount); // 只抽模板
            //$drawPrizes         = $poolGroup->appendPrizes($drawPoolPrizes, $drawTemplatePrizes);
        }
        //各种 修正数据 不影响正常数据处理
        $supInfo = [];
        $result_gift_num = 0;#修正的礼物数量
        if (isset($drawPrizes['supInfo'])) {
            $supInfo = $drawPrizes['supInfo'];
            $result_gift_num = $supInfo['result_gift_num'];
            #补偿的礼物进行数据整合  (从补池里面出来的礼物没有对应的奖池模板 2024.7.11补充注释)
            if (!empty($supInfo['gift_info'])) {
                $drawPrizes[0] = [$supInfo['gift_info']['gift_template_id'] => 1];//
            }
            unset($drawPrizes['supInfo']);
        }

        //更新奖池各礼物抽奖计数和随机种子 抽中幸运礼物, 清空幸运值
        $drawPrizesCount = $poolGroup->getDrawPrizesCount($drawPrizes);

        if ($drawPrizesCount != $drawCount) {
            throw new BasicException(-1, '服务异常');
        }
        DB::connection("mysql_game")->beginTransaction();
        DB::beginTransaction();
        try {
            //奖池礼物扣除
            try {
                $decPoolPrizeRes = $poolGroup->decPoolPrize($drawPrizes);
                if (!$decPoolPrizeRes) {
                    throw new BasicException(-1, '扣减礼物数据更新失败');
                }
            } catch (\Exception $e) {
                if (strpos($e->getMessage(), 'SQLSTATE[22003]') !== false) {
                    throw new BasicException(-1, '服务繁忙，请重试1' . $decPoolPrizeRes);
                } else {
                    throw $e;
                }
            }

            $drawPrizes = $poolGroup->transformDrawPrizes($drawPrizes);
            //用户抽到的礼物
            $gifts      = $this->getGiftList($drawPrizes);

            //添加修正记录
            $clear_money = 0;
            $fragmentExt = [];
            if (!empty($supInfo)) {
                if (!empty($supInfo['account_record'])) {
                    $this->addPoolAccountRecordModel->addRecord($supInfo['account_record']);
                }
                if (!empty($supInfo['check_record'])) {
                    $clear_money = $supInfo['check_record']['clear_money'];
                    $this->checkRecordModel->addRecord($supInfo['check_record']);
                }
                if (!empty($supInfo['check_record_whole'])) {
                    app('model_whole_game_check_record')->insert($supInfo['check_record_whole']);
                }
                if ($supInfo['appoint_gift_id']) {
                    $this->appointGiftModel
                        ->where(['id' => $supInfo['appoint_gift_id']])
                        ->update(['is_valid' => 0, 'valid_time' => date('Y-m-d H:i:s')]);
                }
                //碎片池强制触发
                if ($supInfo['is_force_trigger']) {
                    $fragmentExt['is_force_trigger'] = 1;
                }
            }
            //clear_money不为空，在上面的添加修正记录里面已经将sup_count清空了
            //clear_money为空且奖池为修正池 减去修正池次数
            if (empty($clear_money) && $poolGroup->tag == DrawEnum::POOL_TYPE_SUP) {
                $this->poolUserModel->where('user_id', $user->user_id)->decrement('sup_count', $drawCount);
            }

            //计算投入产出
            $drawIOPut = $this->getDrawIOPut($drawCount, $poolConfig, $gifts, $drawPrizes);

            //用户数据更新
            // 减少用户余额
            $poolUserUpdateData = [];
            $decBalanceData     = $this->decUserBalance($user, $drawCount, $balance);
            if (is_array($decBalanceData)) {
                $poolUserUpdateData += $decBalanceData;
            }

            //累计用户上次抽大奖的计数
            if ($this->isDrawAccumulate) {
                $this->redisObject->hincrby($this->cachePrefix . CacheKey::USER_LAST_BIG_DRAW_COUNT, $user->user_id, $drawCount);
            }

            //触发抽奖计数清零 重新随机种子 用户累计抽奖清零事件
            app('events')->fire('draw.resetCount');

            // 用户投入产出 抽奖数统计
            $poolUserUpdateData += $this->updateUserDrawData($user, $poolGroup, $drawIOPut, $drawCount, $poolConfig);

            //更新用户的上次大奖计数
            if ($this->isDrawAccumulate) {
                $poolUserUpdateData["last_big_draw_count"] = $this->redisObject->hget($this->cachePrefix . CacheKey::USER_LAST_BIG_DRAW_COUNT, $user->user_id);
            }

            try {
                if (!empty($poolUserUpdateData)) {
                    $poolUserUpdateRes = $this->poolUserModel->updateData(['user_id' => $userId], $poolUserUpdateData);

                    if (!$poolUserUpdateRes) {
                        throw new BasicException(-1, '用户数据更新失败');
                    }
                    app('model_whole_game_check_user')->userUpdateData($userId, $drawIOPut);
                }
            } catch (\Exception $e) {
                if (strpos($e->getMessage(), 'SQLSTATE[22003]') !== false) {
                    throw new BasicException(340001, $this->balanceNotEnoughMsg);
                } else {
                    throw $e;
                }
            }

            // 用户背包增加礼物
            $this->sendUserPrizes($userId, $gifts, [], $poolConfig);

            //奖池投入产出 抽奖数统计
            //累计中大奖抽奖次数
            $poolUpdateData = [];
            if ($this->isDrawAccumulate) {
                $poolUpdateData = ['top_count' => DB::raw('top_count +' . $drawCount), 'big_count' => DB::raw('big_count +' . $drawCount)];
            }
            $poolUpdateData += $poolGroup->updatePoolDrawData($drawIOPut, $poolIncrRound, $drawCount);

            if (!empty($poolUpdateData)) {
                $poolUpdateRes = $this->poolModel->updateData(['id' => $poolGroup->pool_id], $poolUpdateData);
                if (!$poolUpdateRes) {
                    throw new BasicException(-1, '奖池数据更新失败');
                }
            }

            //池子自己的额外更新处理
            $extraUpdateRes = $poolGroup->updateExtraData();
            if (!$extraUpdateRes) {
                throw new BasicException(-1, '扩展数据更新失败');
            }

            $drawGroupCount = [];
            foreach ($drawPrizes as $groupId => $groupPrize) {
                foreach ($groupPrize as $prizeId => $prizeCount) {
                    if (isset($drawGroupCount[$groupId])) {
                        $drawGroupCount[$groupId] += $prizeCount;
                    } else {
                        $drawGroupCount[$groupId] = $prizeCount;
                    }
                }
            }
            if ($drawCount > $result_gift_num) {
                //group数据更新
                $poolGroupUpdateRes = $this->updatePoolGroupDrawData($drawIOPut, $poolGroupIncRound, $drawGroupCount);
                if (!$poolGroupUpdateRes) {
                    throw new BasicException(-1, '奖池组合更新失败');
                }
            }


            //排行榜统计
            $this->rankStatistics($gifts, $user, $poolConfig);
            // 添加抽奖记录
            $drawData = $this->addDrawRecord($user, $poolGroup, $drawIOPut, $gifts, $criticalGift, $drawPrizes, $drawCount, $drawPrizesCount);

            $extData['fragmentData'] = $this->dealFragment($user, $drawCount, $poolConfig->toArray(), $gifts->toArray(), $fragmentExt);

            DB::connection("mysql_game")->commit();
            DB::commit();
        } catch (\Exception $e) {
            $this->redisObject->del($lockKey);
//            $this->redisObject->del($this->cachePrefix . "fullPollLock_" . $poolGroup->tag);
            //触发redis回滚事务
            app('events')->fire('draw.redisRollback');
            DB::connection("mysql_game")->rollBack();
            DB::rollBack();
            throw new BasicException($e->getCode(), $e->getMessage());
        }
        // 推送
//        $this->pushMessage($user, $poolConfig, $gifts, $drawPrizes, $criticalGift, $extData);
        $poolGroup->setRedisObject(null);
//        $job = $this->getDrawJob($poolGroup, $user, ['input' => $drawIOPut['input'], 'output' => $drawIOPut['output'], 'gift_list' => $gifts, 'count' => $drawCount]);
//        dispatch($job)->onQueue('isGamePush');

        $this->redisObject->del($lockKey);
        $drawData['user'] = $user;
        return $this->returnDrawResult([
            'draw_data' => $drawData,
            'gift_list' => $gifts->sortByDesc('price')->toArray(),
            'critical_gift' => $criticalGift,
            'poolConfig' => $poolConfig,
            'supInfo' => $supInfo,
            'extData' => $extData,
        ]);
    }

    public function getNotifyGiftList($count)
    {

        $poolConfig       = $this->poolConfigModel->one(['id' => 1], ['notify_coin']);
        $notifyRecordList = $this->poolDrawRecordModel->getNotifyRecordList($poolConfig->notify_coin, $count);
        $giftIds          = $notifyRecordList->pluck('gift_id')->unique()->toArray();
        $userIds          = $notifyRecordList->pluck('user_id')->unique()->toArray();

        $giftList       = (new GiftRepository())->giftsByIds($giftIds);
        $giftListWithId = $giftList->keyBy('id');
        $userListWithId = (new UserDataRepository())->getBaseUserInfosByUserIds($userIds)->keyBy('user_id');

        $notifyRecordList = $notifyRecordList->transform(function ($item) use ($giftListWithId, $userListWithId) {
            $item->gift_name = $giftListWithId[$item->gift_id]['name'];
            $item->nickname  = $userListWithId[$item->user_id]['nickname'];
            return $item;
        });

        return $notifyRecordList;
    }

    public function sendUserPrizes($userId, $gifts, $poolConfig)
    {
//        $poolConfig
        $packageGiftWithId = $gifts->keyBy('id')->toArray();
        $desc = "在{$this->game_name}中获得";
        (new GiftBackpack())->addPrizes($userId, $packageGiftWithId, $desc);
    }

    public function getDrawJob($poolGroup, $user, $jobData)
    {
        return new DrawStatisticsJob($poolGroup, $user, $jobData, $this->cachePrefix);

    }

    public function clearDrawLock($poolGroup)
    {
        //抽奖结束后去除锁
        $this->redisObject->del($this->cachePrefix . CacheKey::POOL_TOP_PRIZE_LIMIT . "_" . $poolGroup->pool_id);
        $this->redisObject->del($this->cachePrefix . CacheKey::POOL_BIG_PRIZE_LIMIT . "_" . $poolGroup->pool_id);
    }

    public function drawCriticalGift($user, int $drawCount, $poolConfig, $poolGroup)
    {
        $criticalPool = $this->poolModel->one(['tag' => DrawEnum::POOL_TYPE_CRITICAL]);
        if (empty($criticalPool)) {
            return '';
        }

        //查询是否有匹配礼物
        $criticalGiftTable = $this->criticalGiftModel->getTable();
        $criticalGift      = $this->criticalGiftModel->getLevelGift($user->level,
            [$criticalGiftTable . '.id', 'gift_id', $criticalGiftTable . '.level', 'name']);
        if (empty($criticalGift)) {
            return '';
        }

        if ($criticalLock = $this->redisObject->setnx($this->cachePrefix . CacheKey::CRITICAL_PRIZE_LIMIT, 1)) {
            $this->redisObject->del($this->cachePrefix . CacheKey::CRITICAL_PRIZE_LIMIT);
        }
        //查询计步器是到数
        if ($criticalPool['big_count'] + $drawCount < $criticalPool['big_random']) {
            //累计计步器
            $this->poolModel->updateData(['id' => $criticalPool->id], ['big_count' => DB::raw('big_count + ' . $drawCount)]);
            return "";
        } else {
            if (!$criticalLock) {
                return "";
            }
            $this->redisObject->setnx($this->cachePrefix . CacheKey::CRITICAL_PRIZE_LIMIT, 1);
            $this->redisObject->expire($this->cachePrefix . CacheKey::CRITICAL_PRIZE_LIMIT, 5);
            //计数器到达后 抽取暴击礼物
            $gift = (new GiftRepository())->one(['id' => $criticalGift['gift_id'], 'is_delete' => 0]);

            if (empty($gift)) {
                return '';
            }

            //减少暴击奖池奖品数量
            $this->criticalGiftModel->updateData(['id' => $criticalGift['id']], ['count' => DB::raw('count - 1')]);
            //清空计步器 增加池子产出
            $bigSection = json_decode($criticalPool->big_step_section, true);
            $this->poolModel->updateData(['id' => $criticalPool->id], ['count' => DB::raw('count + 1'), 'output' => DB::raw('output + ' . $gift->price), 'big_count' => 0, 'big_random' => mt_rand($bigSection[0], $bigSection[1])]);
            //添加暴击奖池奖品记录
            $this->criticalDrawRecordModel->insert(['user_id' => $user->user_id, 'gift_id' => $gift->id, 'gift_price' => $gift->price, 'count' => 1]);
            $gift->level      = $criticalGift->level;
            $gift->count      = 1;
            $gift->level_name = $criticalGift->name;
            $this->redisObject->del($this->cachePrefix . CacheKey::CRITICAL_PRIZE_LIMIT);
            return $gift;
        }

    }


//    public function updateQueuePool($poolGroup)
//    {
//        $this->poolQueueModel->updateData(["id" => $poolGroup->queue_id], ["status" => 1]);
//    }

    public function checkDrawCount($drawCount)
    {
        return true;
    }

    public function rankStatistics(Collection $gifts, $user, $poolConfig)
    {
        //超过通知金额的数量
        $notifyCount   = $gifts->where('price', '>=', $poolConfig->notify_coin)->sum('count');
        $dateCacheKey  = $this->cachePrefix . CacheKey::DATE_RANK . "_" . date("Y-m-d");
        $weekCacheKey  = $this->cachePrefix . CacheKey::WEEK_RANK . "_" . date("W");
        $monthCacheKey = $this->cachePrefix . CacheKey::MONTH_RANK . "_" . date("m");

        $this->redisObject->zincrby($dateCacheKey, $notifyCount, $user->user_id);
        $this->redisObject->zincrby($weekCacheKey, $notifyCount, $user->user_id);
        $this->redisObject->zincrby($monthCacheKey, $notifyCount, $user->user_id);
        $this->redisObject->expire($dateCacheKey, 3 * 24 * 3600);
        $this->redisObject->expire($weekCacheKey, 14 * 24 * 3600);
        $this->redisObject->expire($monthCacheKey, 2 * 30 * 24 * 3600);

        //2025烟火大会活动
        /*$config_info = json_decode(app('model_config')->getValue('NEW_YEAR_FIREWORKS_CONFIG'), true);

        $date_at = date('Y-m-d H:i:s');
        if ($config_info['gift_id'] && $config_info['time_start'] < $date_at && $date_at < $config_info['time_end']) {
            $key = 'new_year:fireworks:user_rank';
            $count = $gifts->where('id', $config_info['gift_id'])->sum('count');
            if (!empty($count)) {
                $activity_redis = app('redis')->connection('activity');
                $score = $activity_redis->zscore($key, $user->user_id) ?? '';
                if (empty($score)) {
                    $oldCount = 0;
                } else {
                    $oldCount = (int)getValueByScore($score);
                }
                $newScore = getScoreByValue($oldCount + $count);
                $activity_redis->zincrby($key, bcsub((string)$newScore, $score), $user->user_id);
            }
        }*/

    }

    public function getUserBalance($userId, $balance)
    {
        return new Collection();
    }

    public function getGiftList(array $drawPrizes)
    {
        //根据模板礼物ID获取礼物ID
        $templateGiftIds = [];
        $giftPrizes      = [];
        foreach ($drawPrizes as $groupId => $groupPrize) {
            foreach ($groupPrize as $prizeId => $prizeCount) {
                $templateGiftIds[] = $prizeId;
                if (isset($giftPrizes[$prizeId])) {
                    $giftPrizes[$prizeId] += $prizeCount;
                } else {
                    $giftPrizes[$prizeId] = $prizeCount;
                }
            }
        }

        $templateGiftList   = $this->giftTemplateModel->getGiftListByIds($templateGiftIds, ['id', 'gift_id']);
        $templateGiftWithId = $templateGiftList->KeyBy('gift_id');
        $giftInfoList       = (new GiftRepository())->giftsByIds($templateGiftList->pluck('gift_id')); // 抽中礼物信息

        foreach ($giftInfoList as $giftInfo) {
            $giftInfo->gift_template_id = $templateGiftWithId[$giftInfo['id']] ? $templateGiftWithId[$giftInfo['id']]['id'] : 0;
            $giftInfo->count            = $giftPrizes[$giftInfo->gift_template_id] ?? 0;
        }
        return $giftInfoList;
    }

    public function updatePoolGroupDrawData(array $drawIOPut, array $poolIncrRound, array $drawGroupCount)
    {
        //更新input output round
        return $this->poolGroupModel->batchUpdateDrawData($drawIOPut, $poolIncrRound, $drawGroupCount);
    }

    public function pushMessage($user, $poolConfig, Collection $gifts, array $drawPrizes, $extraGift, array $extData)
    {

        $broadcastPushData = [];
        $notifyPushData    = [];
        foreach ($drawPrizes as $groupPrize) {
            foreach ($groupPrize as $prizeId => $prizeCount) {
                $gift = $gifts->where('gift_template_id', $prizeId)->first();
                if (empty($gift)) {
                    continue;
                }
                if ($gift->price >= $poolConfig->notify_coin) {
                    $notifyGift        = Collection::make([]);
                    $notifyGift->name  = $gift->name ?? '';
                    $notifyGift->price = $gift->price;
                    $notifyGift->count = $prizeCount;

                    if (isset($notifyPushData[$gift->id])) {
                        $notifyPushData[$gift->id]->count += $notifyGift->count;
                    } else {
                        $notifyPushData[$gift->id] = $notifyGift;
                    }

                }
                if ($gift->price >= $poolConfig->broadcast_coin) {

                    $broadcastGift          = Collection::make([]);
                    $broadcastGift->name    = $gift->name ?? '';
                    $broadcastGift->price   = $gift->price;
                    $broadcastGift->count   = $prizeCount;
                    $broadcastGift->picture = $gift->picture ?? '';
                    if (isset($broadcastPushData[$gift->id])) {
                        $broadcastPushData[$gift->id]->count += $broadcastGift->count;
                    } else {
                        $broadcastPushData[$gift->id] = $broadcastGift;
                    }
                }
            }
        }
        $extraPushData = [];
        if (!empty($extraGift)) {
            $extraPushData[] = $extraGift;
        }
        //碎片的推送
        if (!empty($extData['fragmentData']['send_gift'])) {
            $broadcastGift          = Collection::make([]);// ？？？这样对吗
            $broadcastGift->name    = $extData['fragmentData']['send_gift']['name'];
            $broadcastGift->price   = $extData['fragmentData']['send_gift']['price'];
            $broadcastGift->count   = $extData['fragmentData']['send_gift']['count'];
            $broadcastGift->picture = $extData['fragmentData']['send_gift']['picture'];
            $broadcastPushData[$extData['fragmentData']['send_gift']['id']] = $broadcastGift;
        }

        $this->push($user, $notifyPushData, $broadcastPushData, $extraPushData);
    }

    public function returnDrawResult($drawData)
    {
        return $drawData;
    }

    public abstract function push($user, array $notifyPushData, array $broadcastPushData, array $extraPushData);

    //计算用户抽奖投入产出
    public function getDrawIOPut($drawCount, $poolConfig, $gifts, $drawPrizes)
    {
        $input       = $drawCount * $poolConfig->balance_coin;
        $output      = 0;
        $groupOutput = [];
        $groupInput  = [];
        foreach ($drawPrizes as $groupId => $groupPrize) {
            foreach ($groupPrize as $prizeId => $prizeCount) {
                $gift = $gifts->where('gift_template_id', $prizeId)->first();
                if (empty($gift)) {
                    continue;
                }
                $output += $gift->price * $prizeCount;
                if (isset($groupOutput[$groupId])) {
                    $groupOutput[$groupId] += $gift->price * $prizeCount;
                } else {
                    $groupOutput[$groupId] = $gift->price * $prizeCount;
                }

                if (isset($groupInput[$groupId])) {
                    $groupInput[$groupId] += $poolConfig->balance_coin * $prizeCount;
                } else {
                    $groupInput[$groupId] = $poolConfig->balance_coin * $prizeCount;
                }
            }
        }

        return ['input' => $input, 'output' => $output, 'group_output' => $groupOutput, 'group_input' => $groupInput];
    }

    // 添加抽奖记录
    public function addDrawRecord($user, $poolGroup, array $drawIOPut, Collection $gifts, $criticalGift, array $drawPrizes, int $drawCount, int $drawPrizesCount)
    {
        $drawData = [
            "user_id"    => $user->user_id,
            "group_id"   => $poolGroup->group_id,
            "queue_id"   => $poolGroup->queue_id ?? 0,
            "tag"        => $poolGroup->tag,
            "count"      => $drawCount,
            "gift_count" => $drawPrizesCount,
            "input"      => $drawIOPut['input'],
            "output"     => $drawIOPut['output'],
        ];

        $poolDrawId = $this->poolDrawModel->createDataGetId($drawData);
        if (empty($poolDrawId)) {
            throw new BasicException(-1, '抽奖记录保存错误');
        }
        $drawPrizesRecord = [];
        foreach ($drawPrizes as $groupId => $groupPrize) {
            foreach ($groupPrize as $prizeId => $prizeCount) {
                $gift               = $gifts->where('gift_template_id', $prizeId)->first();
                $drawPrizesRecord[] = ['user_id' => $user->user_id, 'draw_id' => $poolDrawId, 'group_id' => $groupId, 'gift_id' => $gift->id, 'gift_price' => $gift->price, 'count' => $prizeCount];
            }
        }

        $this->poolDrawRecordModel->insert($drawPrizesRecord);


        return $drawData;
    }

//    public function decPoolPrize($poolGroup, array $drawPrizes)
//    {
//        $this->poolPrizeModel->batchDecPrizesByGroup($poolGroup, $drawPrizes);
//    }

    public function updateUserDrawData($user, $poolGroup, array $drawIOPut, int $drawCount, $poolConfig)
    {
        $input          = $drawIOPut['input'];
        $output         = $drawIOPut['output'];
        $userUpdateData = ['input' => DB::raw('input +' . $input), 'output' => DB::raw('output +' . $output),
                           'count' => DB::raw('count +' . $drawCount)];

        //日数据和周数据的新增处理 为了防止并发已缓存中数据为主 数据库后续更新  缓存的值来做数据判断  数据库值来做统计用
        $inputDate  = $this->redisObject->hincrby($this->cachePrefix . CacheKey::USER_DATE_PUT_RECORD . ":$user->user_id" . "_" . date("Y-m-d"), 'input', $input);
        $outputDate = $this->redisObject->hincrby($this->cachePrefix . CacheKey::USER_DATE_PUT_RECORD . ":$user->user_id" . "_" . date("Y-m-d"), 'output', $output);
        $inputWeek  = $this->redisObject->hincrby($this->cachePrefix . CacheKey::USER_WEEK_PUT_RECORD . ":$user->user_id" . "_" . date("Y-W"), 'input', $input);
        $outputWeek = $this->redisObject->hincrby($this->cachePrefix . CacheKey::USER_WEEK_PUT_RECORD . ":$user->user_id" . "_" . date("Y-W"), 'output', $output);
        $this->redisObject->expire($this->cachePrefix . CacheKey::USER_DATE_PUT_RECORD . ":$user->user_id" . "_" . date("Y-m-d"), 72 * 3600);
        $this->redisObject->expire($this->cachePrefix . CacheKey::USER_WEEK_PUT_RECORD . ":$user->user_id" . "_" . date("Y-W"), 14 * 24 * 3600);

        //游戏总统计
        $this->redisObject->hincrby($this->wholePrefix . CacheKey::USER_DATE_PUT_RECORD . ":$user->user_id" . "_" . date("Y-m-d"), 'input', $input);
        $this->redisObject->hincrby($this->wholePrefix . CacheKey::USER_DATE_PUT_RECORD . ":$user->user_id" . "_" . date("Y-m-d"), 'output', $output);
        $this->redisObject->hincrby($this->wholePrefix . CacheKey::USER_WEEK_PUT_RECORD . ":$user->user_id" . "_" . date("Y-W"), 'input', $input);
        $this->redisObject->hincrby($this->wholePrefix . CacheKey::USER_WEEK_PUT_RECORD . ":$user->user_id" . "_" . date("Y-W"), 'output', $output);
        $this->redisObject->expire($this->wholePrefix . CacheKey::USER_DATE_PUT_RECORD . ":$user->user_id" . "_" . date("Y-m-d"), 72 * 3600);
        $this->redisObject->expire($this->wholePrefix . CacheKey::USER_WEEK_PUT_RECORD . ":$user->user_id" . "_" . date("Y-W"), 14 * 24 * 3600);


        app('events')->listen('draw.redisRollback', function () use ($user, $drawIOPut) {
            $this->redisObject->hincrby($this->cachePrefix . CacheKey::USER_DATE_PUT_RECORD . ":$user->user_id" . "_" . date("Y-m-d"), 'input', -$drawIOPut['input']);
            $this->redisObject->hincrby($this->cachePrefix . CacheKey::USER_DATE_PUT_RECORD . ":$user->user_id" . "_" . date("Y-m-d"), 'output', -$drawIOPut['output']);
            $this->redisObject->hincrby($this->cachePrefix . CacheKey::USER_WEEK_PUT_RECORD . ":$user->user_id" . "_" . date("Y-W"), 'input', -$drawIOPut['input']);
            $this->redisObject->hincrby($this->cachePrefix . CacheKey::USER_WEEK_PUT_RECORD . ":$user->user_id" . "_" . date("Y-W"), 'output', -$drawIOPut['output']);

            //总
            $this->redisObject->hincrby($this->wholePrefix . CacheKey::USER_DATE_PUT_RECORD . ":$user->user_id" . "_" . date("Y-m-d"), 'input', -$drawIOPut['input']);
            $this->redisObject->hincrby($this->wholePrefix . CacheKey::USER_DATE_PUT_RECORD . ":$user->user_id" . "_" . date("Y-m-d"), 'output', -$drawIOPut['output']);
            $this->redisObject->hincrby($this->wholePrefix . CacheKey::USER_WEEK_PUT_RECORD . ":$user->user_id" . "_" . date("Y-W"), 'input', -$drawIOPut['input']);
            $this->redisObject->hincrby($this->wholePrefix . CacheKey::USER_WEEK_PUT_RECORD . ":$user->user_id" . "_" . date("Y-W"), 'output', -$drawIOPut['output']);
        });

        $userUpdateData['input_date']  = $inputDate;
        $userUpdateData['output_date'] = $outputDate;
        $userUpdateData['input_week']  = $inputWeek;
        $userUpdateData['output_week'] = $outputWeek;
        //记录用户当前所在组合池子
        $userUpdateData['pool_id'] = $poolGroup->pool_id;

        $userUpdateData['exp']   = DB::raw('exp +' . $drawCount * $poolConfig->balance_coin);
        $level                   = $this->getExpLevel($user->exp + $drawCount * $poolConfig->balance_coin); // 用户等级
        $userUpdateData['level'] = $level;
        return $userUpdateData;

    }

    public function decUserBalance($user, int $drawCount, $balance)
    {
        return ['balance' => DB::raw('balance -' . $drawCount)];
    }

    public function getExpLevel(int $exp)
    {
        return 0;
    }
//
//    // 追加奖励
//    protected function appendPrizes(array $prizes, array $append)
//    {
//        foreach ($append as $prizeId => $prize) {
//            if (isset($prizes[$prize['group_id']][$prizeId])) {
//                $prizes[$prize['group_id']][$prizeId]['count'] += $prize['count'];
//            } else {
//                $prizes[$prize['group_id']][$prizeId]['count'] = $prize['count'];
//            }
//        }
//        return $prizes;
//    }

    public function createNextRoundPrizes($poolGroup, Collection $templatePrizes, int $drawCount)
    {
        // 清空本轮礼物总数
        $this->poolPrizeModel->updateData(['group_id' => $poolGroup->group_id], ['template_count' => 0]);
        $this->poolPrizeModel->appendPrizes($poolGroup, $templatePrizes);
    }

    public function getPoolTemplateGiftList($poolGroup)
    {
        $giftTemplateList = $this->poolTemplateModel->getGiftTemplateList(['group_id' => $poolGroup->group_id], ['gift_template_id', 'count', 'count as template_count', 'gift_id']);
        $giftIds          = $giftTemplateList->pluck('gift_id');
        $gifts            = (new GiftRepository())->giftsByIdsWithField($giftIds, ['id', 'price']); // 抽中礼物信息
        $giftsWithId      = $gifts->keyBy('id');
        foreach ($giftTemplateList as &$template) {
            $template['price']    = $giftsWithId[$template['gift_id']]['price'];
            $template['group_id'] = $poolGroup->group_id;
        }
        return $giftTemplateList;
    }

    public function setAuto($userId, $is_auto = 0)
    {
        $userInfo = $this->poolUserModel->firstOrCreate($userId);
        $userInfo->is_auto = $is_auto;
        $userInfo->save();
        return true;
    }

    public function checkUserBalance($userId, $count): bool
    {
        //todo  用户不存在怎创建 考虑迁移到中间件？
        $userInfo = $this->poolUserModel->firstOrCreate($userId);
        $this->user_info = $userInfo;
        return $userInfo->balance >= $count;
    }

    /**
     * 临时的序列化方法
     * @param $toObject
     * @param $fromObject
     */
    public function serializeObject($toObject, $fromObject)
    {
        $vars = get_object_vars($toObject);
        foreach ($vars as $key => $var) {
            $toObject->{$key} = $fromObject->{$key} ?? '';
        }
    }

    public function getUserPoolGroup($user, int $count, $poolConfig)
    {
        //todo 是否添加缓存处理?  线上数据直接操作数据库 暂时不做缓存处理
        $userId        = $user->user_id;
        $userPoolGroup = null;
        //判断用户是否在队列里
        $userQueue = $this->getUserQueuePool($userId, $count);

        if (!empty($userQueue)) {
            $userPoolGroup = $this->queuePoolGroup;
            $queuePool     = $this->poolModel->one(['tag' => DrawEnum::POOL_TYPE_QUEUE]);
            if (empty($queuePool)) {
                throw new BasicException('奖池未配置');
            }
            $this->serializeObject($userPoolGroup, $queuePool);

            $userPoolGroup->pool_id = $queuePool->id;

            $userPoolGroup->current_group_id = $userQueue->group_id;
            $userPoolGroup->group_id         = $userQueue->group_id;
            $userPoolGroup->queue_id         = $userQueue->id;
            $userPoolGroup->poolPrizeModel   = $this->poolPrizeModel;
            $userPoolGroup->poolQueueModel   = $this->poolQueueModel;
        } else {
            //判断是否开启独立池子 用户是否在独立池子里
            if ($poolConfig->independent_switch) {
                $userIndependentPool = $this->getUserIndependentPool($userId, $count);
                if (!empty($userIndependentPool)) {
                    $userPoolGroup   = $this->independentPoolGroup;
                    $independentPool = $this->poolModel->one(['tag' => DrawEnum::POOL_TYPE_PERSONAGE]);
                    if (!empty($independentPool)) {
                        $this->serializeObject($userPoolGroup, $independentPool);

                        $userPoolGroup->pool_id            = $independentPool->id;
                        $userPoolGroup->independent_id     = $userIndependentPool->id;
                        $userPoolGroup->current_group_id   = $userIndependentPool->group_id;
                        $userPoolGroup->group_id           = $userIndependentPool->group_id;
                        $userPoolGroup->group_ids          = $userIndependentPool->group_ids;
                        $userPoolGroup->remain_group_count = $userIndependentPool->remain_group_count;

                        $userPoolGroup->poolPrizeModel       = $this->poolIndependentPrizeModel;
                        $userPoolGroup->poolIndependentModel = $this->poolIndependentModel;
                    }
                }
            }
            if (empty($userPoolGroup) && $this->isNovicePreset) {
                //判断是否有新手预设
                //判断新手池子盈亏
                if ($this->isNovice($user, $poolConfig)) {
                    $novicePool = $this->poolModel->one(['tag' => DrawEnum::POOL_TYPE_NOVICE]);
                    if (!empty($novicePool)) {
                        if (($novicePool->output - $novicePool->input) >= $poolConfig->novice_loss_limit) {
                            //亏损超过阈值
                            $novicePresetGroup = $this->poolGroupModel->listAll(['pool_id'    => $novicePool->id,
                                                                                 'type'       => DrawEnum::POOL_GROUP_TYPE_PRESET, 'preset_type' => DrawEnum::PRESET_NOVICE_TYPE,
                                                                                 'draw_count' => $count, 'is_earning' => 1, 'status' => 1], ['id']);
                        } else {
                            //亏损没超过阈值
                            $novicePresetGroup = $this->poolGroupModel->listAll(['pool_id'    => $novicePool->id,
                                                                                 'type'       => DrawEnum::POOL_GROUP_TYPE_PRESET, 'preset_type' => DrawEnum::PRESET_NOVICE_TYPE,
                                                                                 'draw_count' => $count, 'is_earning' => 0, 'status' => 1], ['id']);
                        }
                        if ($novicePresetGroup->isNotEmpty()) {
                            $userPoolGroup = $this->novicePoolGroup;
                            $this->serializeObject($userPoolGroup, $novicePool);
                            $userPoolGroup->pool_id          = $novicePool->id;
                            $userPoolGroup->current_group_id = $novicePool->current_group_id;
                            $userPoolGroup->group_id         = $novicePresetGroup->random()->id;
                            $userPoolGroup->poolPrizeModel   = $this->poolPrizeModel;
                        }
                    }
                }
            }
            if (empty($userPoolGroup)) {
                //都不是则进行普通抽取逻辑 普通池子：公池 新手 单抽
                $userPool = $this->getUserPublicPool($user, $count, $poolConfig);
                if (!empty($userPool)) {
                    $userPoolGroup = $this->publicPoolGroup;
                    $this->serializeObject($userPoolGroup, $userPool);
                    $userPoolGroup->pool_id           = $userPool->id;
                    $userPoolGroup->current_group_id  = $userPool->current_group_id;
                    $userPoolGroup->group_id          = $userPool->current_group_id;
                    $userPoolGroup->poolPrizeModel    = $this->poolPrizeModel;
                    $userPoolGroup->poolTemplateModel = $this->poolTemplateModel;
                }
            }
        }
        $userPoolGroup->poolModel      = $this->poolModel;
        $userPoolGroup->poolGroupModel = $this->poolGroupModel;
        $userPoolGroup->checkRecordModel = $this->checkRecordModel;
        $userPoolGroup->addPoolAccountRecordModel = $this->addPoolAccountRecordModel;
        $userPoolGroup->addPoolRepo = $this->addPoolRepo;
        $userPoolGroup->giftTemplateModel = $this->giftTemplateModel;
        //获取当前的奖池组合
        return $userPoolGroup;
    }

    public function getUserPublicPool($user, int $count, $poolConfig)
    {
        //普通池子：公池 新手 单抽
        $poolType = DrawEnum::POOL_TYPE_PUBLIC;
        //修正池剩余次数>=此次抽奖次数
        if ($user->sup_count >= $count && $this->addPoolRepo->start() ) {
            $poolType = DrawEnum::POOL_TYPE_SUP;
        } else if ($this->isNovice($user, $poolConfig)) {
            $poolType = DrawEnum::POOL_TYPE_NOVICE;
        } else if ($count == 1) {
            #2013.12.14去掉单抽池
            //$poolType = DrawEnum::POOL_TYPE_SINGLE;
        }
        //当类型不为公共池时，判定该奖池是否有正常使用的模板
        if ($poolType != DrawEnum::POOL_TYPE_PUBLIC) {
            $pool = $this->poolModel->one(['tag' => $poolType]);
            $poolGroup = $this->poolGroupModel->one(['pool_id' => $pool->id, 'status' => 1]);
            if (empty($poolGroup)) {
                $poolType = DrawEnum::POOL_TYPE_PUBLIC;
            }
        }

        return $this->poolModel->one(['tag' => $poolType]);
    }

    public function isNovice($user, $poolConfig)
    {
        return $user->input_week <= $poolConfig->novice_coin;
    }

    public function getUserQueuePool($userId, int $count)
    {
        return $this->poolQueueModel->one(['user_id' => $userId, 'draw_count' => $count, 'status' => 0], 'id');

    }

    public function getUserIndependentPool($userId, $count)
    {
        //2023.12.17需求，独立池子打完一轮自动退出
        /*$data = $this->poolIndependentModel->where('user_id', $userId)->first();
        if (empty($data) || $data->status != 1) {
            return [];
        }
        $where = [
            'independent_id' => $data->id, 'user_id' => $userId
        ];
        $userPrizeList = $this->poolIndependentPrizeModel->where($where)->get();
        //刚添加的时候 独立池是空的
        if (empty($userPrizeList->toArray())) {
            return $data;
        }
        #是否有未生成的模板
        $group_ary = explode(',', $data->group_ids);
        $get_group_ary = $userPrizeList->pluck('group_id')->unique()->toArray();
        $diff = array_diff($group_ary, $get_group_ary);
        if (!empty($diff)) {
            return $data;
        }
        #剩余抽数
        $sum_count = $userPrizeList->sum('count');
        if (empty($sum_count)) {
            $data->status = 2;
            $data->save();
        }
        if ($sum_count > $count) {
            return $data;
        }
        return [];*/


        //独立池子需要判断数量是否充足 不充足拉取下一个独自池子
        $poolIndependentTable = $this->poolIndependentModel->getTable();
        $userIndependentList  = $this->poolIndependentModel->getListWithPrize([$poolIndependentTable . '.user_id' => $userId, 'status' => 1],
            [$poolIndependentTable . '.id', 'group_ids', $poolIndependentTable . '.group_id', 'remain_group_count', 'count']);
        $independentCount     = [];
        foreach ($userIndependentList as $independent) {
            if ($independent['remain_group_count'] >= 1) {
                //有剩余数量则直接返回
                return $independent;
            } else {
                if (isset($independentCount[$independent['id']][$independent['group_id']]['count'])) {
                    $independentCount[$independent['id']][$independent['group_id']]['count'] += $independent['count'];
                } else {
                    $independentCount[$independent['id']][$independent['group_id']]['count'] = 0;
                }

                if ($independentCount[$independent['id']][$independent['group_id']]['count'] >= $count) {
                    return $independent;
                }
            }
        }

        return [];
    }

    public function clearUserIO($userId)
    {
        $inputDate  = $this->redisObject->hincrby($this->cachePrefix . CacheKey::USER_DATE_PUT_RECORD . ":$userId" . "_" . date("Y-m-d"), 'input', 0);
        $inputWeek  = $this->redisObject->hincrby($this->cachePrefix . CacheKey::USER_WEEK_PUT_RECORD . ":$userId" . "_" . date("Y-W"), 'input', 0);
        $this->redisObject->expire($this->cachePrefix . CacheKey::USER_DATE_PUT_RECORD . ":$userId" . "_" . date("Y-m-d"), 72 * 3600);
        $this->redisObject->expire($this->cachePrefix . CacheKey::USER_WEEK_PUT_RECORD . ":$userId" . "_" . date("Y-W"), 14 * 24 * 3600);

        $update = [];
        //当天投入为0
        if (empty($inputDate)) {
            $update['input_date'] = $update['output_date'] = 0;
        }
        if (empty($inputWeek)) {
            $update['input_week'] = $update['output_week'] = 0;
        }
        if (!empty($update)) {
            $this->poolUserModel->where('user_id', $userId)->update($update);
        }

        //游戏总清空
        $inputDateWhole  = $this->redisObject->hincrby($this->wholePrefix . CacheKey::USER_DATE_PUT_RECORD . ":$userId" . "_" . date("Y-m-d"), 'input', 0);
        $inputWeekWhole  = $this->redisObject->hincrby($this->wholePrefix . CacheKey::USER_WEEK_PUT_RECORD . ":$userId" . "_" . date("Y-W"), 'input', 0);
        $this->redisObject->expire($this->wholePrefix . CacheKey::USER_DATE_PUT_RECORD . ":$userId" . "_" . date("Y-m-d"), 72 * 3600);
        $this->redisObject->expire($this->wholePrefix . CacheKey::USER_WEEK_PUT_RECORD . ":$userId" . "_" . date("Y-W"), 14 * 24 * 3600);

        $updateWhole = [];
        //当天投入为0
        if (empty($inputDateWhole)) {
            $updateWhole['input_date'] = $updateWhole['output_date'] = 0;
        }
        if (empty($inputWeekWhole)) {
            $updateWhole['input_week'] = $updateWhole['output_week'] = 0;
        }
        if (!empty($updateWhole)) {
            app('model_whole_game_check_user')->where('user_id', $userId)->update($updateWhole);
        }
    }

    //显示飘屏的等级
    public function showBroadcastGrade($show_type = 'draw')
    {
        $default_grade = 9999;
        $show_broadcast_grade = app('model_config')->getValue('SHOW_BROADCAST_GRADE');
        if (empty($show_broadcast_grade)) {
            return $default_grade;
        }
        $show_broadcast_grade = json_decode($show_broadcast_grade, true);
        return $show_broadcast_grade[$show_type] ?? $default_grade;
    }


    public function getAllPlutocratList()
    {
//        $balance_coin = $this->poolConfigModel->value('balance_coin');
        // 要是一样的兑换b得换掉
        $key = "RICH_AWARD_" . strtoupper($this->privateKey);
        $gift = app('model_config')->getValue($key);
        if (empty($gift)) {
            return [];
        }
        $giftIds = explode(',', $gift);
        return app('model_gift')->whereIn("id", $giftIds)->orderByDesc('price')->select(['name', 'picture', 'price'])->get()->toArray() ?? [];
    }

    public function prizeListByValue($perPage, $page)
    {
        $config_value   = app("model_config")->getValue("SHOW_PRIZE_VALUE") ?: 520;
        if(empty($config_value) || !is_numeric($config_value)) {
            return [];
        }
        $list   = $this->poolDrawRecordModel->from($this->poolDrawRecordModel->getTable() ." as log")
            ->leftJoin(app('model_gift')->getTable() ." as gift", 'log.gift_id', '=', 'gift.id')
            ->leftJoin(app('model_user')->getTable() ." as user",'log.user_id', '=', 'user.id')
            ->where('gift.price', '>=', $config_value)
            ->orderByDesc('log.id')
            ->paginate($perPage, ['user.avatar', 'user.nickname', 'gift.title', 'gift.price', 'gift.img', 'log.created_at'], '', $page)->toArray();

        foreach ($list['data'] as &$value) {
            $value['created_at'] = substr($value['created_at'], 0, -3);
        }
        return $list;

    }

    //处理碎片
    public function dealFragment($user, int $drawCount, array $poolConfig, array $gifts, array $extra = []) {
        return [];
    }

    public function getFragmentGroupList()
    {
        return RedisService::getDrawFragmentGroup($this->cachePrefix, $this->fragmentGroupModel, $this->giftTemplateModel);
    }

    public function getFragmentUserRecordList($prePage, $page, $userId, $type)
    {
        $with = [
            'user:id as user_id,nickname,user_number as user_code,avatar as head_picture',
            'send_gift:id,title as name,price,img as picture',
        ];
        if ($this->privateKey == 'frag') {
            $with[] = 'fragment_group:id,name,is_all';
        }
        $where = [];
        if ($type == 1) {
            $where['user_id'] = $userId;
        }
        return $this->fragmentUserRecordModel
            ->where($where)
            ->with($with)
            ->orderBy('id', 'desc')
            ->paginate($prePage, ['*'], '', $page);
    }

    /**
     * @param $match *匹配的键
     * @param int $type *类型 1删除 2 更新过期时间
     * @param int $expireTime *过期时间
     */
    protected function cursorRedisKey($match, $type = 1, $expireTime = 0)
    {
        $cursor = 0;
        while (true) {
            [$cursor, $keys] = $this->redisObject->scan($cursor, ['MATCH' => $match]);
            if ($type == 1) {
                $this->redisObject->del($keys);
            } else {
                foreach ($keys as $key) {
                    $this->redisObject->expire($key, $expireTime);
                }
            }

            if ($cursor == 0) {
                break;
            }
        }
    }


    public function drawRecord($perPage, $page, $userId)
    {
        $fields = ['id', 'user_id', 'count', 'gift_count', 'created_at'];
        $with = [
            'user:id,nickname,user_number,avatar',
            'draw_record:id,draw_id,gift_id,gift_price,count',
        ];
        $gift_list = array_column(array_column($this->giftTemplateModel->with('gift')->get()->toArray(), 'gift'), NULL, 'id');
        $list = $this->poolDrawModel
            ->with($with)->where('user_id', $userId)
            ->orderBy('id', 'desc')
            ->paginate($perPage, $fields, 'page', $page)->toArray();
        foreach ($list['data'] as &$value) {
            foreach ($value['draw_record'] as &$record) {
                $record['gift_name'] = $gift_list[$record['gift_id']]['title'] ?? '未知礼物';
                $record['gift_img'] = $gift_list[$record['gift_id']]['img'] ?? '';
            }
            $value['created_at'] = substr($value['created_at'], 0, -3);
        }
        return $list;

    }
}
